home *** CD-ROM | disk | FTP | other *** search
- // When In Rome
- // Mac Hack XI - MCMXCVI
- // Barry Semo
- // barrys@netcom.com
-
- #include "A4Stuff.h"
- #include "SetupA4.h"
- #include <LString.h>
-
- typedef pascal void (*DrawStringProc)(ConstStr255Param s);
- typedef pascal short (*StringWidthProc)(ConstStr255Param s);
-
- pascal void DrawStringPatch(ConstStr255Param s);
- pascal short StringWidthPatch(ConstStr255Param s);
-
- Boolean IsDigit(char c);
- void ToRoman(long decimal, Str255 roman);
- void ParseString(Str255 string);
-
- DrawStringProc gOldDrawStringAddr;
- StringWidthProc gOldStringWidthAddr;
-
- Str15 gSymbols[] = {"\pM", "\pCM", "\pD", "\pCD", "\pC", "\pXC", "\pL",
- "\pXL", "\pX", "\pIX", "\pV", "\pIV", "\pI"};
- short gValue[13] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
-
- void main(void)
- {
- long oldA4;
- Handle h;
-
- // a4 world
- oldA4 = SetCurrentA4();
- RememberA4();
-
- // detach init resource
- h = Get1Resource('INIT', 0);
- if (h) DetachResource(h);
-
- // initialize
- gOldDrawStringAddr = 0L;
-
- // patch
- gOldDrawStringAddr = (DrawStringProc)GetToolTrapAddress(_DrawString);
- SetToolTrapAddress((UniversalProcPtr)DrawStringPatch, _DrawString);
-
- gOldStringWidthAddr = (StringWidthProc)GetToolTrapAddress(_StringWidth);
- SetToolTrapAddress((UniversalProcPtr)StringWidthPatch, _StringWidth);
-
- // restore a4
- SetA4(oldA4);
- }
-
- // DrawString patch that converts a number to roman numeral equivalents
- pascal void DrawStringPatch(ConstStr255Param s)
- {
- long oldA4;
- LStr255 decimalNumber;
- Str255 tempString;
-
- oldA4 = SetUpA4();
-
- LString::CopyPStr(s, tempString);//tempCopy
- ParseString(tempString);
- gOldDrawStringAddr(tempString);
-
- RestoreA4(oldA4);
- }
-
- // StringWidth patch that returns the width of a converted string
- pascal short StringWidthPatch(ConstStr255Param s)
- {
- long oldA4;
- LStr255 decimalNumber;
- Str255 tempString;
- short width;
-
- oldA4 = SetUpA4();
-
- LString::CopyPStr(s, tempString);//temp copy
- ParseString(tempString);
- width = gOldStringWidthAddr(tempString);
-
- RestoreA4(oldA4);
-
- return width;
- }
-
- // return if a char is a digit 0-9
- Boolean IsDigit(char c)
- {
- return (c >= '0') && (c <= '9');
- }
-
- void ToRoman(long decimal, Str255 roman)
- {
- short i=0;
- LStr255 destStr;
-
- //convert to roman, reducing number by largest roman numeral first,
- //working downward
- while (decimal > 0) {
- if (gValue[i] <= decimal)
- {
- destStr += gSymbols[i];
- decimal -= gValue[i];
- }
- else
- i++;
- }
-
- //copy it back
- LString::CopyPStr(destStr, roman);
- }
-
- // parse a string for embedde numbers, converting them to roman numerals, and
- // regParseStringenerating the string
- void ParseString(Str255 string)
- {
- LStr255 destStr("\p");
- Str255 romanNum;
- long currentNum = 0L;
- short length = string[0];
- short i;
- Boolean seenDigit = false;
-
- for (i= 1; i<= length; i++)
- {
- if (IsDigit(string[i]))
- {
- seenDigit = true;
- currentNum = (currentNum*10) + (string[i]-'0');//accumulate number
- }
- else//not a digit
- if (seenDigit)//just terminated a number
- {
- ToRoman(currentNum, romanNum);
-
- destStr += romanNum;
- destStr += string[i];
-
- //reset for next time
- seenDigit = false;
- currentNum = 0L;
- }
- else
- destStr += string[i];
- }
-
- // if a number was being accumulated, terminate it
- if (currentNum != 0L)
- {
- ToRoman(currentNum, romanNum);
- destStr += romanNum;
- }
-
- // copy back to parameter passed in
- LString::CopyPStr(destStr, string);
- }
-
-